home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Developers / src / out-of-phase-102-c / OutOfPhase 1.02 Source / OutOfPhase Folder / SampleStorageDisplay.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-23  |  30.5 KB  |  972 lines  |  [TEXT/KAHL]

  1. /* SampleStorageDisplay.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
  5. /*    Copyright (C) 1994  Thomas R. Lawrence                                 */
  6. /*                                                                           */
  7. /*    This program is free software; you can redistribute it and/or modify   */
  8. /*    it under the terms of the GNU General Public License as published by   */
  9. /*    the Free Software Foundation; either version 2 of the License, or      */
  10. /*    (at your option) any later version.                                    */
  11. /*                                                                           */
  12. /*    This program is distributed in the hope that it will be useful,        */
  13. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  14. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
  15. /*    GNU General Public License for more details.                           */
  16. /*                                                                           */
  17. /*    You should have received a copy of the GNU General Public License      */
  18. /*    along with this program; if not, write to the Free Software            */
  19. /*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
  20. /*                                                                           */
  21. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  22. /*                                                                           */
  23. /*****************************************************************************/
  24.  
  25. #include "MiscInfo.h"
  26. #include "Audit.h"
  27. #include "Debug.h"
  28. #include "Definitions.h"
  29.  
  30. #include "SampleStorageDisplay.h"
  31. #include "Memory.h"
  32. #include "DataMunging.h"
  33. #include "Scrap.h"
  34. #include "Files.h"
  35.  
  36.  
  37. #define MAGICSCRAPSTRING ("\xff\x00\x1f\xfe SampleStorageScrap")
  38.  
  39. typedef struct
  40.     {
  41.         char                                    MagicString[sizeof(MAGICSCRAPSTRING)];
  42.         NumBitsType                        NumberOfBits;
  43.         NumChannelsType                NumberOfChannels;
  44.         long                                    NumberOfBytes;
  45.     } SampleClipboardRec;
  46.  
  47.  
  48. struct SampleStorageDisplayRec
  49.     {
  50.         NumBitsType                        NumberOfBits;
  51.         NumChannelsType                MonoStereo;
  52.         largefixedsigned*            Buffer;
  53.         MyBoolean                            DataHasChanged;
  54.  
  55.         MyBoolean                            UndoFileIsValid;
  56.         FileType*                            TheUndoFile;
  57.         FileSpec*                            TheUndoFileLocation;
  58.     };
  59.  
  60.  
  61. /* create a zero-length sample storage object */
  62. SampleStorageDisplayRec*    NewSampleStorageDisplayEmpty(NumBitsType NumBits,
  63.                                                         NumChannelsType NumChannels)
  64.     {
  65.         SampleStorageDisplayRec*    Storage;
  66.  
  67.         ERROR((NumBits != eSample16bit) && (NumBits != eSample8bit),
  68.             PRERR(ForceAbort,"NewSampleStorageDisplayEmpty:  invalid value for NewNumBits"));
  69.         ERROR((NumChannels != eSampleMono) && (NumChannels != eSampleStereo),
  70.             PRERR(ForceAbort,"NewSampleStorageDisplayEmpty:  invalid number of channels"));
  71.         Storage = (SampleStorageDisplayRec*)AllocPtrCanFail(
  72.             sizeof(SampleStorageDisplayRec),"SampleStorageDisplayRec");
  73.         if (Storage == NIL)
  74.             {
  75.              FailurePoint1:
  76.                 return NIL;
  77.             }
  78.         Storage->Buffer = (largefixedsigned*)AllocPtrCanFail(0,"SampleDataArray");
  79.         if (Storage->Buffer == NIL)
  80.             {
  81.              FailurePoint2:
  82.                 ReleasePtr((char*)Storage);
  83.                 goto FailurePoint1;
  84.             }
  85.         Storage->NumberOfBits = NumBits;
  86.         Storage->MonoStereo = NumChannels;
  87.         Storage->DataHasChanged = False;
  88.         Storage->UndoFileIsValid = False;
  89.         return Storage;
  90.     }
  91.  
  92.  
  93. /* create a zero-length sample storage object */
  94. SampleStorageDisplayRec*    NewSampleStorageDisplayData(NumBitsType NumBits,
  95.                                                         NumChannelsType NumChannels, largefixedsigned* DataBlock)
  96.     {
  97.         SampleStorageDisplayRec*    Storage;
  98.  
  99.         ERROR((NumBits != eSample16bit) && (NumBits != eSample8bit),
  100.             PRERR(ForceAbort,"NewSampleStorageDisplayData:  invalid value for NewNumBits"));
  101.         ERROR((NumChannels != eSampleMono) && (NumChannels != eSampleStereo),
  102.             PRERR(ForceAbort,"NewSampleStorageDisplayData:  invalid number of channels"));
  103.         CheckPtrExistence(DataBlock);
  104.         Storage = (SampleStorageDisplayRec*)AllocPtrCanFail(
  105.             sizeof(SampleStorageDisplayRec),"SampleStorageDisplayRec");
  106.         if (Storage == NIL)
  107.             {
  108.              FailurePoint1:
  109.                 return NIL;
  110.             }
  111.         Storage->Buffer = DataBlock;
  112.         SetTag(DataBlock,"SampleDataArray");
  113.         ERROR((NumChannels == eSampleStereo) && ((PtrSize((char*)DataBlock)
  114.             % (2 * sizeof(largefixedsigned))) != 0),PRERR(ForceAbort,
  115.             "NewSampleStorageDisplayData:  stereo sample not an even number of elements"));
  116.         Storage->NumberOfBits = NumBits;
  117.         Storage->MonoStereo = NumChannels;
  118.         Storage->DataHasChanged = False;
  119.         Storage->UndoFileIsValid = False;
  120.         return Storage;
  121.     }
  122.  
  123.  
  124. /* dispose of a sample storage object */
  125. void                                            DisposeSampleStorageDisplay(SampleStorageDisplayRec* Storage)
  126.     {
  127.         CheckPtrExistence(Storage);
  128.         SampleStorageDisplayFlushUndo(Storage);
  129.         ReleasePtr((char*)Storage->Buffer);
  130.         ReleasePtr((char*)Storage);
  131.     }
  132.  
  133.  
  134. /* get the number of bits being represented in this sample */
  135. NumBitsType                                GetSampleStorageDisplayNumBits(
  136.                                                         SampleStorageDisplayRec* Storage)
  137.     {
  138.         CheckPtrExistence(Storage);
  139.         return Storage->NumberOfBits;
  140.     }
  141.  
  142.  
  143. /* get the number of channels being represented in this sample */
  144. NumChannelsType                        GetSampleStorageDisplayNumChannels(
  145.                                                         SampleStorageDisplayRec* Storage)
  146.     {
  147.         CheckPtrExistence(Storage);
  148.         return Storage->MonoStereo;
  149.     }
  150.  
  151.  
  152. /* get the number of frames stored in this object */
  153. long                                            GetSampleStorageDisplayNumFrames(
  154.                                                         SampleStorageDisplayRec* Storage)
  155.     {
  156.         long                                        TheLengthThang;
  157.  
  158.         CheckPtrExistence(Storage);
  159.         TheLengthThang = PtrSize((char*)Storage->Buffer);
  160.         TheLengthThang = TheLengthThang / sizeof(largefixedsigned);
  161.         if (Storage->MonoStereo == eSampleStereo)
  162.             {
  163.                 TheLengthThang = TheLengthThang / 2;
  164.             }
  165.         return TheLengthThang;
  166.     }
  167.  
  168.  
  169. /* get a value from in the array */
  170. largefixedsigned                    GetSampleStorageDisplayValue(SampleStorageDisplayRec* Storage,
  171.                                                         long Index, ChannelType WhichChannel)
  172.     {
  173.         largefixedsigned                ReturnValue;
  174.  
  175.         CheckPtrExistence(Storage);
  176.         ERROR((Index < 0) || (Index >= GetSampleStorageDisplayNumFrames(Storage)),
  177.             PRERR(ForceAbort,"GetSampleStorageDisplayValue:  index out of range"));
  178.         switch (Storage->MonoStereo)
  179.             {
  180.                 default:
  181.                     EXECUTE(PRERR(ForceAbort,
  182.                         "GetSampleStorageDisplayValue:  bad internal number of channels"));
  183.                     break;
  184.                 case eSampleStereo:
  185.                     switch (WhichChannel)
  186.                         {
  187.                             default:
  188.                                 EXECUTE(PRERR(ForceAbort,
  189.                                 "GetSampleStorageDisplayValue:  bad channel selector"));
  190.                                 break;
  191.                             case eLeftChannel:
  192.                                 PRNGCHK(Storage->Buffer,&(Storage->Buffer[Index * 2]),
  193.                                     sizeof(largefixedsigned));
  194.                                 ReturnValue = Storage->Buffer[Index * 2];
  195.                                 break;
  196.                             case eRightChannel:
  197.                                 PRNGCHK(Storage->Buffer,&(Storage->Buffer[(Index * 2) + 1]),
  198.                                     sizeof(largefixedsigned));
  199.                                 ReturnValue = Storage->Buffer[(Index * 2) + 1];
  200.                                 break;
  201.                         }
  202.                     break;
  203.                 case eSampleMono:
  204.                     switch (WhichChannel)
  205.                         {
  206.                             default:
  207.                                 EXECUTE(PRERR(ForceAbort,
  208.                                 "GetSampleStorageDisplayValue:  bad channel selector"));
  209.                                 break;
  210.                             case eMonoChannel:
  211.                                 PRNGCHK(Storage->Buffer,&(Storage->Buffer[Index]),
  212.                                     sizeof(largefixedsigned));
  213.                                 ReturnValue = Storage->Buffer[Index];
  214.                                 break;
  215.                         }
  216.                     break;
  217.             }
  218.         return ReturnValue;
  219.     }
  220.  
  221.  
  222. /* find out if the array has been changed since last being saved */
  223. MyBoolean                                    DoesSampleStorageDisplayNeedToBeSaved(
  224.                                                         SampleStorageDisplayRec* Storage)
  225.     {
  226.         CheckPtrExistence(Storage);
  227.         return Storage->DataHasChanged;
  228.     }
  229.  
  230.  
  231. /* change the number of bits being used to store the data */
  232. void                                            SetSampleStorageDisplayNumBits(
  233.                                                         SampleStorageDisplayRec* Storage, NumBitsType NewNumBits)
  234.     {
  235.         CheckPtrExistence(Storage);
  236.         ERROR((NewNumBits != eSample16bit) && (NewNumBits != eSample8bit),
  237.             PRERR(ForceAbort,"SetSampleStorageDisplayNumBits:  invalid value for NewNumBits"));
  238.         Storage->NumberOfBits = NewNumBits;
  239.         Storage->DataHasChanged = True;
  240.     }
  241.  
  242.  
  243. /* change the number of channels being stored in the array */
  244. MyBoolean                                    SetSampleStorageDisplayNumChannels(
  245.                                                         SampleStorageDisplayRec* Storage,
  246.                                                         NumChannelsType NewNumChannels)
  247.     {
  248.         CheckPtrExistence(Storage);
  249.         ERROR((NewNumChannels != eSampleMono) && (NewNumChannels != eSampleStereo),
  250.             PRERR(ForceAbort,"SetSampleStorageDisplayNumChannels:  invalid number of channels"));
  251.         if (Storage->MonoStereo != NewNumChannels)
  252.             {
  253.                 largefixedsigned*                NewBuffer;
  254.                 long                                        Scan;
  255.                 long                                        NumSampleFrames;
  256.  
  257.                 NumSampleFrames = GetSampleStorageDisplayNumFrames(Storage);
  258.                 if (NewNumChannels == eSampleStereo)
  259.                     {
  260.                         /* convert mono to stereo */
  261.                         NewBuffer = (largefixedsigned*)AllocPtrCanFail(sizeof(largefixedsigned)
  262.                             * NumSampleFrames * 2,"SampleStorageDisplay Data");
  263.                         if (NewBuffer == NIL)
  264.                             {
  265.                                 return False;
  266.                             }
  267.                         for (Scan = 0; Scan < NumSampleFrames; Scan += 1)
  268.                             {
  269.                                 PRNGCHK(NewBuffer,&(NewBuffer[2 * Scan + 0]),
  270.                                     sizeof(NewBuffer[2 * Scan + 0]));
  271.                                 PRNGCHK(Storage->Buffer,&(Storage->Buffer[Scan]),
  272.                                     sizeof(Storage->Buffer[Scan]));
  273.                                 NewBuffer[2 * Scan + 0] = Storage->Buffer[Scan];
  274.                                 PRNGCHK(NewBuffer,&(NewBuffer[2 * Scan + 1]),
  275.                                     sizeof(NewBuffer[2 * Scan + 1]));
  276.                                 NewBuffer[2 * Scan + 1] = Storage->Buffer[Scan];
  277.                             }
  278.                     }
  279.                  else
  280.                     {
  281.                         /* convert stereo to mono */
  282.                         NewBuffer = (largefixedsigned*)AllocPtrCanFail(sizeof(largefixedsigned)
  283.                             * NumSampleFrames,"SampleStorageDisplay Data");
  284.                         if (NewBuffer == NIL)
  285.                             {
  286.                                 return False;
  287.                             }
  288.                         for (Scan = 0; Scan < NumSampleFrames; Scan += 1)
  289.                             {
  290.                                 PRNGCHK(NewBuffer,&(NewBuffer[Scan]),sizeof(NewBuffer[Scan]));
  291.                                 PRNGCHK(Storage->Buffer,&(Storage->Buffer[2 * Scan + 0]),
  292.                                     sizeof(Storage->Buffer[2 * Scan + 0]));
  293.                                 PRNGCHK(Storage->Buffer,&(Storage->Buffer[2 * Scan + 1]),
  294.                                     sizeof(Storage->Buffer[2 * Scan + 1]));
  295.                                 NewBuffer[Scan] = (Storage->Buffer[2 * Scan + 0]
  296.                                     + Storage->Buffer[2 * Scan + 1]) / 2;
  297.                             }
  298.                     }
  299.                 ReleasePtr((char*)Storage->Buffer);
  300.                 Storage->Buffer = NewBuffer;
  301.                 Storage->MonoStereo = NewNumChannels;
  302.                 Storage->DataHasChanged = True;
  303.             }
  304.         return True;
  305.     }
  306.  
  307.  
  308. /* change the value of one of the sample points */
  309. void                                            SetSampleStorageDisplayValue(SampleStorageDisplayRec* Storage,
  310.                                                         long Index, ChannelType WhichChannel,
  311.                                                         largefixedsigned NewValue)
  312.     {
  313.         CheckPtrExistence(Storage);
  314.         ERROR((Index < 0) || (Index >= GetSampleStorageDisplayNumFrames(Storage)),
  315.             PRERR(ForceAbort,"SetSampleStorageDisplayValue:  index out of range"));
  316.         Storage->DataHasChanged = True;
  317.         switch (Storage->MonoStereo)
  318.             {
  319.                 default:
  320.                     EXECUTE(PRERR(ForceAbort,
  321.                         "GetSampleStorageDisplayValue:  bad internal number of channels"));
  322.                     break;
  323.                 case eSampleStereo:
  324.                     switch (WhichChannel)
  325.                         {
  326.                             default:
  327.                                 EXECUTE(PRERR(ForceAbort,
  328.                                 "GetSampleStorageDisplayValue:  bad channel selector"));
  329.                                 break;
  330.                             case eLeftChannel:
  331.                                 PRNGCHK(Storage->Buffer,&(Storage->Buffer[Index * 2]),
  332.                                     sizeof(largefixedsigned));
  333.                                 Storage->Buffer[Index * 2] = NewValue;
  334.                                 break;
  335.                             case eRightChannel:
  336.                                 PRNGCHK(Storage->Buffer,&(Storage->Buffer[(Index * 2) + 1]),
  337.                                     sizeof(largefixedsigned));
  338.                                 Storage->Buffer[(Index * 2) + 1] = NewValue;
  339.                                 break;
  340.                         }
  341.                     break;
  342.                 case eSampleMono:
  343.                     switch (WhichChannel)
  344.                         {
  345.                             default:
  346.                                 EXECUTE(PRERR(ForceAbort,
  347.                                 "GetSampleStorageDisplayValue:  bad channel selector"));
  348.                                 break;
  349.                             case eMonoChannel:
  350.                                 PRNGCHK(Storage->Buffer,&(Storage->Buffer[Index]),
  351.                                     sizeof(largefixedsigned));
  352.                                 Storage->Buffer[Index] = NewValue;
  353.                                 break;
  354.                         }
  355.                     break;
  356.             }
  357.     }
  358.  
  359.  
  360. /* indicate that the object has been saved */
  361. void                                            SampleStorageDisplayHasBeenSaved(
  362.                                                         SampleStorageDisplayRec* Storage)
  363.     {
  364.         CheckPtrExistence(Storage);
  365.         Storage->DataHasChanged = False;
  366.     }
  367.  
  368.  
  369. /* insert a bunch of zeros into the array */
  370. MyBoolean                                    InsertSampleStorageDisplayArea(
  371.                                                         SampleStorageDisplayRec* Storage, long Index,
  372.                                                         long NumFramesToInsert)
  373.     {
  374.         long                                        Start;
  375.         long                                        NumBytes;
  376.         long                                        OldSize;
  377.         char*                                        NewBuffer;
  378.         long                                        Scan;
  379.  
  380.         CheckPtrExistence(Storage);
  381.         ERROR((Index < 0) || (Index >/*NB*/ GetSampleStorageDisplayNumFrames(Storage)),
  382.             PRERR(ForceAbort,"InsertSampleStorageDisplayArea:  index out of range"));
  383.         ERROR(NumFramesToInsert < 0,PRERR(ForceAbort,
  384.             "InsertSampleStorageDisplayArea:  number of frames is negative"));
  385.         Storage->DataHasChanged = True;
  386.         OldSize = PtrSize((char*)Storage->Buffer);
  387.         Start = Index * sizeof(largefixedsigned);
  388.         NumBytes = NumFramesToInsert * sizeof(largefixedsigned);
  389.         if (Storage->MonoStereo == eSampleStereo)
  390.             {
  391.                 NumBytes *= 2;
  392.                 Start *= 2;
  393.             }
  394.         NewBuffer = ResizePtr((char*)Storage->Buffer,OldSize + NumBytes);
  395.         if (NewBuffer == NIL)
  396.             {
  397.                 return False;
  398.             }
  399.         Storage->Buffer = (largefixedsigned*)NewBuffer;
  400.         PRNGCHK(NewBuffer,&(NewBuffer[Start]),OldSize - Start);
  401.         PRNGCHK(NewBuffer,&(NewBuffer[Start + NumBytes]),OldSize - Start);
  402.         MoveData(&(NewBuffer[Start]),&(NewBuffer[Start + NumBytes]),OldSize - Start);
  403.         for (Scan = Start; Scan < Start + NumBytes; Scan += 1)
  404.             {
  405.                 NewBuffer[Scan] = 0;
  406.             }
  407.         return True;
  408.     }
  409.  
  410.  
  411. /* delete a range of values from the array */
  412. MyBoolean                                    DeleteSampleStorageDisplayArea(
  413.                                                         SampleStorageDisplayRec* Storage, long Index,
  414.                                                         long NumFramesToDelete)
  415.     {
  416.         long                                        Start;
  417.         long                                        NumBytes;
  418.         long                                        OldSize;
  419.         char*                                        NewBuffer;
  420.  
  421.         CheckPtrExistence(Storage);
  422.         ERROR((Index < 0) || (Index + NumFramesToDelete
  423.             > GetSampleStorageDisplayNumFrames(Storage)),
  424.             PRERR(ForceAbort,"DeleteSampleStorageDisplayArea:  index out of range"));
  425.         ERROR(NumFramesToDelete < 0,PRERR(ForceAbort,
  426.             "DeleteSampleStorageDisplayArea:  number of frames is negative"));
  427.         Storage->DataHasChanged = True;
  428.         OldSize = PtrSize((char*)Storage->Buffer);
  429.         Start = Index * sizeof(largefixedsigned);
  430.         NumBytes = NumFramesToDelete * sizeof(largefixedsigned);
  431.         if (Storage->MonoStereo == eSampleStereo)
  432.             {
  433.                 NumBytes *= 2;
  434.                 Start *= 2;
  435.             }
  436.         NewBuffer = RemoveBlockFromBlockCopy((char*)Storage->Buffer,Start,NumBytes);
  437.         if (NewBuffer == NIL)
  438.             {
  439.                 return False;
  440.             }
  441.         ReleasePtr((char*)Storage->Buffer);
  442.         Storage->Buffer = (largefixedsigned*)NewBuffer;
  443.         return True;
  444.     }
  445.  
  446.  
  447. /* extract part of the sample & create another sample record containing it */
  448. SampleStorageDisplayRec*    ExtractSampleStorageDisplaySection(
  449.                                                         SampleStorageDisplayRec* Storage, long Index,
  450.                                                         long NumFramesToExtract)
  451.     {
  452.         SampleStorageDisplayRec*    NewStorage;
  453.         long                                            Start;
  454.         long                                            NumBytes;
  455.         char*                                            NewBuffer;
  456.  
  457.         CheckPtrExistence(Storage);
  458.         ERROR(((Index < 0) || (Index + NumFramesToExtract
  459.             > GetSampleStorageDisplayNumFrames(Storage))),
  460.             PRERR(ForceAbort,"ExtractSampleStorageDisplaySection:  index out of range"));
  461.         ERROR(NumFramesToExtract < 0,PRERR(ForceAbort,
  462.             "ExtractSampleStorageDisplaySection:  number of frames is negative"));
  463.         Start = Index * sizeof(largefixedsigned);
  464.         NumBytes = NumFramesToExtract * sizeof(largefixedsigned);
  465.         if (Storage->MonoStereo == eSampleStereo)
  466.             {
  467.                 NumBytes *= 2;
  468.                 Start *= 2;
  469.             }
  470.         NewBuffer = AllocPtrCanFail(NumBytes,"SampleDataBuffer");
  471.         if (NewBuffer != NIL)
  472.             {
  473.                 PRNGCHK(Storage->Buffer,&(((char*)Storage->Buffer)[Start]),NumBytes);
  474.                 PRNGCHK(NewBuffer,&(NewBuffer[0]),NumBytes);
  475.                 CopyData(&(((char*)Storage->Buffer)[Start]),&(NewBuffer[0]),NumBytes);
  476.                 NewStorage = NewSampleStorageDisplayData(Storage->NumberOfBits,
  477.                     Storage->MonoStereo,(largefixedsigned*)NewBuffer);
  478.                 if (NewStorage == NIL)
  479.                     {
  480.                         ReleasePtr(NewBuffer);
  481.                         NewStorage = NIL;
  482.                     }
  483.             }
  484.         return NewStorage;
  485.     }
  486.  
  487.  
  488. /* insert one sample into another at a certain point */
  489. MyBoolean                                    InsertSampleStorageDisplaySection(
  490.                                                         SampleStorageDisplayRec* Storage, long Index,
  491.                                                         SampleStorageDisplayRec* DataToInsert)
  492.     {
  493.         long                                        NumFramesToInsert;
  494.         NumChannelsType                    TheirNumChannels;
  495.         NumChannelsType                    OurNumChannels;
  496.  
  497.         CheckPtrExistence(Storage);
  498.         ERROR((Index < 0) || (Index > GetSampleStorageDisplayNumFrames(Storage)),
  499.             PRERR(ForceAbort,"InsertSampleStorageDisplaySection:  index is out of range"));
  500.         Storage->DataHasChanged = True;
  501.         NumFramesToInsert = GetSampleStorageDisplayNumFrames(DataToInsert);
  502.         TheirNumChannels = GetSampleStorageDisplayNumChannels(DataToInsert);
  503.         OurNumChannels = GetSampleStorageDisplayNumChannels(Storage);
  504.         if (InsertSampleStorageDisplayArea(Storage,Index,NumFramesToInsert))
  505.             {
  506.                 long                        Scan;
  507.  
  508.                 if (TheirNumChannels == eSampleStereo)
  509.                     {
  510.                         if (OurNumChannels == eSampleStereo)
  511.                             {
  512.                                 /* them stereo and us stereo */
  513.                                 for (Scan = 0; Scan < NumFramesToInsert; Scan += 1)
  514.                                     {
  515.                                         SetSampleStorageDisplayValue(Storage,Scan + Index,eLeftChannel,
  516.                                             GetSampleStorageDisplayValue(DataToInsert,Scan,eLeftChannel));
  517.                                         SetSampleStorageDisplayValue(Storage,Scan + Index,eRightChannel,
  518.                                             GetSampleStorageDisplayValue(DataToInsert,Scan,eRightChannel));
  519.                                     }
  520.                             }
  521.                          else
  522.                             {
  523.                                 /* them stereo and us mono; average their samples as we insert */
  524.                                 for (Scan = 0; Scan < NumFramesToInsert; Scan += 1)
  525.                                     {
  526.                                         SetSampleStorageDisplayValue(Storage,Scan + Index,eMonoChannel,
  527.                                             (GetSampleStorageDisplayValue(DataToInsert,Scan,eLeftChannel)
  528.                                             + GetSampleStorageDisplayValue(DataToInsert,Scan,eRightChannel))
  529.                                             / 2);
  530.                                     }
  531.                             }
  532.                     }
  533.                  else
  534.                     {
  535.                         if (OurNumChannels == eSampleStereo)
  536.                             {
  537.                                 /* them mono and us stereo; duplicate their samples */
  538.                                 for (Scan = 0; Scan < NumFramesToInsert; Scan += 1)
  539.                                     {
  540.                                         SetSampleStorageDisplayValue(Storage,Scan + Index,eLeftChannel,
  541.                                             GetSampleStorageDisplayValue(DataToInsert,Scan,eMonoChannel));
  542.                                         SetSampleStorageDisplayValue(Storage,Scan + Index,eRightChannel,
  543.                                             GetSampleStorageDisplayValue(DataToInsert,Scan,eMonoChannel));
  544.                                     }
  545.                             }
  546.                          else
  547.                             {
  548.                                 /* them mono and us mono */
  549.                                 for (Scan = 0; Scan < NumFramesToInsert; Scan += 1)
  550.                                     {
  551.                                         SetSampleStorageDisplayValue(Storage,Scan + Index,eMonoChannel,
  552.                                             GetSampleStorageDisplayValue(DataToInsert,Scan,eMonoChannel));
  553.                                     }
  554.                             }
  555.                     }
  556.                 return True;
  557.             }
  558.          else
  559.             {
  560.                 return False;
  561.             }
  562.     }
  563.  
  564.  
  565. /* dump the contents of the object and install a copy of the contents of another */
  566. MyBoolean                                    SampleStorageDisplaySetContents(
  567.                                                         SampleStorageDisplayRec* Storage,
  568.                                                         SampleStorageDisplayRec* NewData)
  569.     {
  570.         char*                                        Copy;
  571.  
  572.         CheckPtrExistence(Storage);
  573.         CheckPtrExistence(NewData);
  574.         Copy = CopyPtr((char*)NewData->Buffer);
  575.         if (Copy == NIL)
  576.             {
  577.                 return False;
  578.             }
  579.         ReleasePtr((char*)Storage->Buffer);
  580.         Storage->Buffer = (largefixedsigned*)Copy;
  581.         Storage->NumberOfBits = NewData->NumberOfBits;
  582.         Storage->MonoStereo = NewData->MonoStereo;
  583.         Storage->DataHasChanged = True;
  584.         return True;
  585.     }
  586.  
  587.  
  588. /* put the raw data for the sample onto the clipboard */
  589. void                                            PutSampleStorageDisplayOnClipboard(
  590.                                                         SampleStorageDisplayRec* Storage)
  591.     {
  592.         char*                                        Buffer;
  593.  
  594.         CheckPtrExistence(Storage);
  595.         Buffer = AllocPtrCanFail(sizeof(SampleClipboardRec)
  596.             + PtrSize((char*)Storage->Buffer),"SampleScrap");
  597.         if (Buffer == NIL)
  598.             {
  599.                 return;
  600.             }
  601.         CopyData(MAGICSCRAPSTRING,&(((SampleClipboardRec*)Buffer)->MagicString[0]),
  602.             sizeof(MAGICSCRAPSTRING));
  603.         ((SampleClipboardRec*)Buffer)->NumberOfBits = Storage->NumberOfBits;
  604.         ((SampleClipboardRec*)Buffer)->NumberOfChannels = Storage->MonoStereo;
  605.         ((SampleClipboardRec*)Buffer)->NumberOfBytes = PtrSize((char*)Storage->Buffer);
  606.         CopyData((char*)Storage->Buffer,(char*)Buffer + sizeof(SampleClipboardRec),
  607.             PtrSize((char*)Storage->Buffer));
  608.         SetScrapToThis(Buffer);
  609.         ReleasePtr(Buffer);
  610.     }
  611.  
  612.  
  613. /* get a sample off the clipboard.  returns NIL if the scrap isn't a sample */
  614. SampleStorageDisplayRec*    GetSampleStorageDisplayFromClipboard(void)
  615.     {
  616.         char*                                        Buffer;
  617.         SampleStorageDisplayRec*    Storage;
  618.         long                                        Scan;
  619.         char*                                        BufferResized;
  620.         NumBitsType                            NumBits;
  621.         NumChannelsType                    NumChannels;
  622.  
  623.         Buffer = GetCopyOfScrap();
  624.         if (Buffer == NIL)
  625.             {
  626.                 return NIL;
  627.             }
  628.         if (PtrSize(Buffer) < sizeof(SampleClipboardRec))
  629.             {
  630.              NotEnoughMemory:
  631.              NotOurScrap:
  632.                 ReleasePtr(Buffer);
  633.                 return NIL;
  634.             }
  635.         for (Scan = 0; Scan < sizeof(MAGICSCRAPSTRING); Scan += 1)
  636.             {
  637.                 if (MAGICSCRAPSTRING[Scan] != ((SampleClipboardRec*)Buffer)->MagicString[Scan])
  638.                     {
  639.                         goto NotOurScrap;
  640.                     }
  641.             }
  642.         if (sizeof(SampleClipboardRec) + ((SampleClipboardRec*)Buffer)->NumberOfBytes
  643.             != PtrSize(Buffer))
  644.             {
  645.                 goto NotOurScrap;
  646.             }
  647.         if ((((SampleClipboardRec*)Buffer)->NumberOfBits != eSample8bit)
  648.             && (((SampleClipboardRec*)Buffer)->NumberOfBits != eSample16bit))
  649.             {
  650.                 goto NotOurScrap;
  651.             }
  652.         if ((((SampleClipboardRec*)Buffer)->NumberOfChannels != eSampleMono)
  653.             && (((SampleClipboardRec*)Buffer)->NumberOfChannels != eSampleStereo))
  654.             {
  655.                 goto NotOurScrap;
  656.             }
  657.         NumBits = ((SampleClipboardRec*)Buffer)->NumberOfBits;
  658.         NumChannels = ((SampleClipboardRec*)Buffer)->NumberOfChannels;
  659.         MoveData(Buffer + sizeof(SampleClipboardRec),Buffer,
  660.             PtrSize(Buffer) - sizeof(SampleClipboardRec));
  661.         BufferResized = ResizePtr(Buffer,PtrSize(Buffer) - sizeof(SampleClipboardRec));
  662.         if (BufferResized == NIL)
  663.             {
  664.                 goto NotEnoughMemory;
  665.             }
  666.         Storage = NewSampleStorageDisplayData(NumBits,NumChannels,
  667.             (largefixedsigned*)BufferResized);
  668.         if (Storage == NIL)
  669.             {
  670.                 ReleasePtr(BufferResized);
  671.                 return NIL;
  672.             }
  673.         return Storage;
  674.     }
  675.  
  676.  
  677. /* get a copy of a particular channel of data from the sample */
  678. largefixedsigned*                    SampleStorageDisplayGetChannelFixed(
  679.                                                         SampleStorageDisplayRec* Storage, ChannelType WhichChannel)
  680.     {
  681.         largefixedsigned*                Data;
  682.         long                                        Limit;
  683.  
  684.         CheckPtrExistence(Storage);
  685.         Limit = GetSampleStorageDisplayNumFrames(Storage);
  686.         Data = (largefixedsigned*)AllocPtrCanFail(sizeof(largefixedsigned)
  687.             * Limit,"SampleFixed");
  688.         if (Data != NIL)
  689.             {
  690.                 long                                Scan;
  691.  
  692.                 for (Scan = 0; Scan < Limit; Scan += 1)
  693.                     {
  694.                         Data[Scan] = GetSampleStorageDisplayValue(Storage,Scan,WhichChannel);
  695.                     }
  696.             }
  697.         return Data;
  698.     }
  699.  
  700.  
  701. /* put a new block of data into the sample object.  a copy of the block is made */
  702. MyBoolean                                    SampleStorageDisplayPutMonoFixed(
  703.                                                         SampleStorageDisplayRec* Storage, largefixedsigned* Data)
  704.     {
  705.         long                                        Difference;
  706.         long                                        Scan;
  707.         long                                        Limit;
  708.  
  709.         CheckPtrExistence(Storage);
  710.         CheckPtrExistence(Data);
  711.         ERROR(PtrSize((char*)Data) % sizeof(largefixedsigned) != 0,PRERR(ForceAbort,
  712.             "SampleStorageDisplayPutMonoFixed:  array alignment error"));
  713.         Limit = PtrSize((char*)Data) / sizeof(largefixedsigned);
  714.         Difference = Limit - GetSampleStorageDisplayNumFrames(Storage);
  715.         if (Difference > 0)
  716.             {
  717.                 /* new data is bigger, so we insert the difference */
  718.                 if (!InsertSampleStorageDisplayArea(Storage,
  719.                     GetSampleStorageDisplayNumFrames(Storage),Difference))
  720.                     {
  721.                         return False;
  722.                     }
  723.             }
  724.         else if (Difference < 0)
  725.             {
  726.                 /* new data is smaller, so we delete the difference */
  727.                 Difference = - Difference;
  728.                 if (!DeleteSampleStorageDisplayArea(Storage,
  729.                     GetSampleStorageDisplayNumFrames(Storage) - Difference,Difference))
  730.                     {
  731.                         return False;
  732.                     }
  733.             }
  734.         /* else don't do anything */
  735.         ERROR(GetSampleStorageDisplayNumFrames(Storage) != Limit,PRERR(ForceAbort,
  736.             "SampleStorageDisplayPutMonoFixed:  storage size inconsistency"));
  737.         for (Scan = 0; Scan < Limit; Scan += 1)
  738.             {
  739.                 SetSampleStorageDisplayValue(Storage,Scan,eMonoChannel,Data[Scan]);
  740.             }
  741.         return True;
  742.     }
  743.  
  744.  
  745. /* put two new blocks of data into a stereo sample object.  copies are made */
  746. MyBoolean                                    SampleStorageDisplayPutStereoFixed(
  747.                                                         SampleStorageDisplayRec* Storage, largefixedsigned* Left,
  748.                                                         largefixedsigned* Right)
  749.     {
  750.         long                                        Difference;
  751.         long                                        Scan;
  752.         long                                        Limit;
  753.  
  754.         CheckPtrExistence(Storage);
  755.         ERROR(PtrSize((char*)Left) != PtrSize((char*)Right),PRERR(ForceAbort,
  756.             "SampleStoragePutStereoFixed:  Left and Right sizes are not equal"));
  757.         ERROR(PtrSize((char*)Left) % sizeof(largefixedsigned) != 0,PRERR(ForceAbort,
  758.             "SampleStoragePutStereoFixed:  array alignment error"));
  759.         Limit = PtrSize((char*)Left) / sizeof(largefixedsigned);
  760.         Difference = Limit - GetSampleStorageDisplayNumFrames(Storage);
  761.         if (Difference > 0)
  762.             {
  763.                 /* new data is bigger, so we insert the difference */
  764.                 if (!InsertSampleStorageDisplayArea(Storage,
  765.                     GetSampleStorageDisplayNumFrames(Storage),Difference))
  766.                     {
  767.                         return False;
  768.                     }
  769.             }
  770.         else if (Difference < 0)
  771.             {
  772.                 /* new data is smaller, so we delete the difference */
  773.                 Difference = - Difference;
  774.                 if (!DeleteSampleStorageDisplayArea(Storage,
  775.                     GetSampleStorageDisplayNumFrames(Storage) - Difference,Difference))
  776.                     {
  777.                         return False;
  778.                     }
  779.             }
  780.         /* else don't do anything */
  781.         ERROR(GetSampleStorageDisplayNumFrames(Storage) != Limit,PRERR(ForceAbort,
  782.             "SampleStoragePutStereoFixed:  storage size inconsistency"));
  783.         for (Scan = 0; Scan < Limit; Scan += 1)
  784.             {
  785.                 SetSampleStorageDisplayValue(Storage,Scan,eLeftChannel,Left[Scan]);
  786.                 SetSampleStorageDisplayValue(Storage,Scan,eRightChannel,Right[Scan]);
  787.             }
  788.         return True;
  789.     }
  790.  
  791.  
  792. /* flush any undo information */
  793. void                                            SampleStorageDisplayFlushUndo(SampleStorageDisplayRec* Storage)
  794.     {
  795.         CheckPtrExistence(Storage);
  796.         if (Storage->UndoFileIsValid)
  797.             {
  798.                 CloseFile(Storage->TheUndoFile);
  799.                 DeleteFile(Storage->TheUndoFileLocation);
  800.                 DisposeFileSpec(Storage->TheUndoFileLocation);
  801.                 Storage->UndoFileIsValid = False;
  802.             }
  803.     }
  804.  
  805.  
  806. /* save the object to a temporary file so that we can undo any changes. */
  807. /* if it couldn't be done, then it returns False */
  808. MyBoolean                                    SampleStorageDisplaySetupForUndo(SampleStorageDisplayRec* Storage)
  809.     {
  810.         long                                        BufferLength;
  811.  
  812.         CheckPtrExistence(Storage);
  813.         SampleStorageDisplayFlushUndo(Storage);
  814.  
  815.         /* try to obtain a temporary file */
  816.         Storage->TheUndoFileLocation = NewTempFileSpec(CODE4BYTES('?','?','?','?'),
  817.             CODE4BYTES('?','?','?','?'));
  818.         if (Storage->TheUndoFileLocation == NIL)
  819.             {
  820.                 /* couldn't be done */
  821.              FailurePoint1:
  822.                 return False;
  823.             }
  824.  
  825.         /* try to open it */
  826.         if (!OpenFile(Storage->TheUndoFileLocation,&(Storage->TheUndoFile),eReadAndWrite))
  827.             {
  828.              FailurePoint2:
  829.                 DeleteFile(Storage->TheUndoFileLocation);
  830.                 DisposeFileSpec(Storage->TheUndoFileLocation);
  831.                 goto FailurePoint2;
  832.             }
  833.  
  834.         /* save data */
  835.         if (0 != WriteToFile(Storage->TheUndoFile,(char*)&(Storage->NumberOfBits),
  836.             sizeof(Storage->NumberOfBits)))
  837.             {
  838.              FailurePoint3:
  839.                 CloseFile(Storage->TheUndoFile);
  840.                 goto FailurePoint2;
  841.             }
  842.         if (0 != WriteToFile(Storage->TheUndoFile,(char*)&(Storage->MonoStereo),
  843.             sizeof(Storage->MonoStereo)))
  844.             {
  845.              FailurePoint4:
  846.                 goto FailurePoint3;
  847.             }
  848.         BufferLength = PtrSize((char*)Storage->Buffer);
  849.         if (0 != WriteToFile(Storage->TheUndoFile,(char*)&BufferLength,sizeof(long)))
  850.             {
  851.              FailurePoint5:
  852.                 goto FailurePoint4;
  853.             }
  854.         if (0 != WriteToFile(Storage->TheUndoFile,(char*)Storage->Buffer,BufferLength))
  855.             {
  856.              FailurePoint6:
  857.                 goto FailurePoint5;
  858.             }
  859.  
  860.         /* wow, we made it through, so we get to set this little flag thingie here! */
  861.         Storage->UndoFileIsValid = True;
  862.  
  863.         return True;
  864.     }
  865.  
  866.  
  867. /* find out if we can undo something */
  868. MyBoolean                                    SampleStorageDisplayUndoAvailable(SampleStorageDisplayRec* Storage)
  869.     {
  870.         CheckPtrExistence(Storage);
  871.         return Storage->UndoFileIsValid;
  872.     }
  873.  
  874.  
  875. /* try to undo something.  returns True if the undo data was successfully recovered. */
  876. /* the current state is swapped with the recovered state */
  877. MyBoolean                                    SampleStorageDisplayUndo(SampleStorageDisplayRec* Storage)
  878.     {
  879.         MyBoolean                                OldUndoIsValid;
  880.         FileType*                                OldUndoFile;
  881.         FileSpec*                                OldUndoFileLocation;
  882.  
  883.         NumBitsType                            LocalNumberOfBits;
  884.         NumChannelsType                    LocalMonoStereo;
  885.         long                                        NumberOfBytes;
  886.         largefixedsigned*                LocalBuffer;
  887.  
  888.  
  889.         CheckPtrExistence(Storage);
  890.         ERROR(!Storage->UndoFileIsValid,PRERR(ForceAbort,
  891.             "SampleStorageDisplayUndo:  there is no saved undo information"));
  892.  
  893.         /* save old undo information so we can recover stuff */
  894.         OldUndoIsValid = Storage->UndoFileIsValid;
  895.         OldUndoFile = Storage->TheUndoFile;
  896.         OldUndoFileLocation = Storage->TheUndoFileLocation;
  897.  
  898.         /* save current state for undoing */
  899.         Storage->UndoFileIsValid = False; /* DON'T discard previous information */
  900.         if (!SampleStorageDisplaySetupForUndo(Storage))
  901.             {
  902.                 /* failed -- restore state & return */
  903.              FailurePoint1:
  904.                 Storage->UndoFileIsValid = OldUndoIsValid;
  905.                 Storage->TheUndoFile = OldUndoFile;
  906.                 Storage->TheUndoFileLocation = OldUndoFileLocation;
  907.                 return False;
  908.             }
  909.  
  910.         /* now try to build new information for us */
  911.         if (!SetFilePosition(OldUndoFile,0))
  912.             {
  913.              FailurePoint2:
  914.                 goto FailurePoint1;
  915.             }
  916.  
  917.         /* read in cute informations */
  918.         if (0 != ReadFromFile(OldUndoFile,(char*)&LocalNumberOfBits,sizeof(LocalNumberOfBits)))
  919.             {
  920.              FailurePoint3:
  921.                 goto FailurePoint2;
  922.             }
  923.         if (0 != ReadFromFile(OldUndoFile,(char*)&LocalMonoStereo,sizeof(LocalMonoStereo)))
  924.             {
  925.              FailurePoint4:
  926.                 goto FailurePoint3;
  927.             }
  928.         if (0 != ReadFromFile(OldUndoFile,(char*)&NumberOfBytes,sizeof(long)))
  929.             {
  930.              FailurePoint5:
  931.                 goto FailurePoint4;
  932.             }
  933.         LocalBuffer = (largefixedsigned*)AllocPtrCanFail(NumberOfBytes,"SampleDataArray");
  934.         if (LocalBuffer == NIL)
  935.             {
  936.              FailurePoint6:
  937.                 goto FailurePoint5;
  938.             }
  939.         if (0 != ReadFromFile(OldUndoFile,(char*)LocalBuffer,NumberOfBytes))
  940.             {
  941.              FailurePoint7:
  942.                 ReleasePtr((char*)LocalBuffer);
  943.                 goto FailurePoint6;
  944.             }
  945.  
  946.         /* now we've successfully read all of the data in.  */
  947.         /* we can replace current data with read in data & discard local undo stuff */
  948.  
  949.         /* dispose old undo information */
  950.         CloseFile(OldUndoFile);
  951.         DeleteFile(OldUndoFileLocation);
  952.         DisposeFileSpec(OldUndoFileLocation);
  953.  
  954.         /* dump current information */
  955.         Storage->NumberOfBits = LocalNumberOfBits;
  956.         Storage->MonoStereo = LocalMonoStereo;
  957.         ReleasePtr((char*)Storage->Buffer);
  958.         Storage->Buffer = LocalBuffer;
  959.  
  960.         Storage->DataHasChanged = True;
  961.  
  962.         return True;
  963.     }
  964.  
  965.  
  966. /* get the actual raw data in the channel */
  967. largefixedsigned*                    SampleStorageDisplayGetActualData(SampleStorageDisplayRec* Storage)
  968.     {
  969.         CheckPtrExistence(Storage);
  970.         return Storage->Buffer;
  971.     }
  972.